package com.lry.jvm.instructions.refrences;
//创建基本类型数组 new int[];

import com.lry.jvm.instructions.base.BytecodeReader;
import com.lry.jvm.instructions.base.NoOperandsInstruction;
import com.lry.jvm.rtda.Frame;
import com.lry.jvm.rtda.JObject;
import com.lry.jvm.rtda.OperandStack;
import com.lry.jvm.rtda.heap.JClass;
import com.lry.jvm.rtda.heap.JClassLoader;
import com.lry.jvm.util.Util;

//newarray指令需要两个操作数。第一个操作数是一个uint8整 数，
// 在字节码中紧跟在指令操作码后面，
// 表示要创建哪种类型的数 组。Java虚拟机规范把这个操作数叫作atype
// ，并且规定了它的有效 值。把这些值定义为常量
public class newarray extends NoOperandsInstruction {
    private static final byte AT_BOOLEAN = 4;
    private static final byte AT_CHAR = 5;
    private static final byte AT_FLOAT = 6;
    private static final byte AT_DOUBLE = 7;
    private static final byte AT_BYTE = 8;
    private static final byte AT_SHORT = 9;
    private static final byte AT_INT = 10;
    private static final byte AT_LONG = 11;

    private byte atype;

    @Override
    public byte getOpCode() {
        return (byte) 0xbc;
    }

    @Override
    public void fetchOperands(BytecodeReader reader) {
        atype = reader.read8();
    }

    @Override
    public void execute(Frame frame) throws Exception {
        OperandStack stack = frame.getOperandStack();
        //数组长度
        int len = stack.popInt();
        if(len<0){
            Util.panic("java.lang.NegativeArraySizeException");
        }

        JClassLoader loader = frame.getMethod().getJClass().getLoader();
        JClass arrClass = getPrimitiveArrayClass(loader,atype);
        JObject arr = arrClass.newArray(len);
        stack.pushRef(arr);
    }

    private JClass getPrimitiveArrayClass(JClassLoader loader, byte atype) {
        switch (atype){
            case AT_BOOLEAN:
                return loader.loadClass("[Z");
            case AT_BYTE:
                return loader.loadClass("[B");
            case AT_CHAR:
                return loader.loadClass("[C");
            case AT_SHORT:
                return loader.loadClass("[S");
            case AT_INT:
                return loader.loadClass("[I");
            case AT_LONG:
                return loader.loadClass("[J");
            case AT_FLOAT:
                return loader.loadClass("[F");
            case AT_DOUBLE:
                return loader.loadClass("[D");
            default:
                Util.panic("Invalid atype");
                return null;
        }
    }
}
